React Hook 是 React 16.8 中新增的功能,它解決了以下幾個問題:
class
也能使用 state
和 React 其他的功能,使得 function component 能更有效的被使用。DOM
等行為,都會產生 side effect(副作用)。在 class component 中,我們透過 componentDidMount
、componentDidUpdate
、componentWillUnmount
這幾個方法來處理 side effect。透過 React Hook,我們在 function component 中只要利用一個叫 useEffect
的方法即可處理,更為簡便易用。useReducer
、useContext
功能做處理。class
在學習及使用上都更為複雜,class component 對於目前的一些開發工具來說也不好壓縮。useState
能讓 function component 使用 state
,下面是它的一個基本使用方式。useState
中有一個參數initState
,是初始的 state
。initState
可以是任意類型的值,也可以是一個回調函式,但必須有返回值。我們調用 useState
後會返回一個陣列,陣列內的兩個值 state
是我們要設置的狀態,setState
是更新陣列內 state
的函式。
const [state, setState] = useState(initState)
下面為一個簡單的加數字功能範例,我們使用 useState
來設定 state
、更新方法及初始值,透過 onClick
觸發 setCount
去改變 state
。
// 引用 useEffect
import { useState } from 'react';
const Test = () => {
// 設定 state、更新方法及初始值
const [count, setCount] = useState(0)
return <div>
<div>{ count }</div>
<div><button onClick={ () => setCount(count + 1) }>click</button></div>
</div>
}
useEffect
如前面所述,是用來處理 side effect 用的,也是 componentDidMount
、componentDidUpdate
、componentWillUnmount
三個函式的統一。它接受兩個參數,callback
和 array
,callback
是我們處理 side effect 的回調函式,array
是決定 useEffect
的執行。useEffect
是在元件第一次 render
和每次 render
時會執行
所有的 side effect 行為都應該在 useEffect 裡面處理,另外也可以透過返回一個函式來進行清理,如下面的 return
,它會在元件卸載時候自動調用,相當於 class component 的 componentWillUnmount
。
useEffect(() => {
// side effect
return () => {
// 清理工作,類似 componentWillUnmount
}
})
array
參數控制 useEffect
的執行,如果是空陣列,就只會在元件第一次 render
後執行,相當於 componentDidMount
,如果陣列內有值,那會在陣列內的值發生改變後執行。還有一種情況是沒有 array
參數,那 useEffect
就會在每一次 render
後都執行一次。陣列內的值可以是元件內的 state
,或是元件外傳入的 props
。
useEffect(() => {
// side effect
}, []) // 第一次 render 時,執行一次
useEffect(() => {
// side effect
}, [count]) // 陣列內的值發生變化時執行
useEffect(() => {
// side effect
}) // 每次次 render 時,都執行一次
下面的範例中,count
每次發生改變,useEffect
都會執行一次。
import { useState, useEffect } from 'react';
const Test = () => {
// 設定 state、更新方法及初始值
const [count, setCount] = useState(0)
useEffect(() => {
//手動修改 react dom
document.title = `點擊了${count}次`
}, [count])// count 每次改變,useEffect 都會執行一次
return <div>
<div>{ count }</div>
<div><button onClick={ () => setCount(count + 1) }>click</button></div>
</div>
}
我們也可以同時使用多個 useEffect
,以下面的範例來說,我們就可以決定在不同時間點渲染時,去執行不同的事情。
const Test = () => {
// 設定 state、更新方法及初始值
const [count, setCount] = useState(0
useEffect(() => {
document.title = `還沒點擊`
}, [])// 第一次 render 時執行
useEffect(() => {
// side effect
document.title = `點擊了${count}次`
}, [count]) // count 每次改變,useEffect 都會執行
return <div>
<div>{ count }</div>
<div><button onClick={ () => setCount(count + 1) }>click</button></div>
</div>
}
我們也可以在 useEffect
進行遠端資料請求,如下面利用空陣列,在第一次 render
時請求資料
const Test = () => {
// 設定 state、更新方法及初始值
const [data, setData] = useState(0
const fetchData = async () => {
const result = await fetch('./user.json').then(res => res.json())
setData()
}
useEffect(() => {
//手動修改 react dom
fetchData()
}, [])// count 每次改變,useEffect 都會執行一次
return <div>
<div>{ data }</div>
</div>
}
React 中有兩種常見的 side effect 類型,一種需要清理,一種不需要,如下
useEffect
會在每次執行之前,自動清理之前的 side effect。